#ifndef COMMON_H
#define COMMON_H
#ifdef _DEBUG
#define _CRTDBG_MAP_ALLOC
#endif
#include "widget_config.h"
#include <math.h>
const double PI = 3.14159265358979323846;
#ifndef MAX
   #define  MAX( x, y ) ( ((x) > (y)) ? (x) : (y) )
#endif

#ifndef MIN
   #define  MIN( x, y ) ( ((x) < (y)) ? (x) : (y) )
#endif
//typedef unsigned short WCHAR;

#ifndef NULL
#define NULL 0
#endif

#define COPY_FIELD(POINTER,FIELD) (POINTER)->FIELD=FIELD
typedef struct _WEXTENT{
   int   width;
   int   height;
} WExtent;
class DLL_EXP WPoint
{
public:
	WPoint()
	{
		x=0;
		y=0;
		z=0;
	}
	WPoint(int x,int y,int z)
	{
		this->x=x;
		this->y=y;
		this->z=z;
	}
	inline friend int operator == (const WPoint r1, const WPoint r2)
	{
		if(r1.x==r2.x && r1.y==r2.y && r1.z==r2.z )
		{
			return true;
		}
		return false;
	};
	inline WPoint& operator = (const WPoint &r)            { 
		x=r.x;
		y=r.y;
		z=r.z;
		
		return *this;
	};
	int x,y,z;

};

class CBmpTransfromRotateY;
class DLL_EXP WRect
{
public:
	WRect()
	{
		x=0;
		y=0;
		z=0;
		dx=0;
		dy=0;
	}
	inline friend int operator == (const WRect r1, const WRect r2)
	{
		if(r1.x==r2.x && r1.y==r2.y && r1.z==r2.z && r1.dx==r2.dx && r1.dy==r2.dy)
		{
			return true;
		}
		return false;
	};
	inline WRect& operator = (const WRect &r)            { 
		x=r.x;
		y=r.y;
		z=r.z;
		dx=r.dx;
		dy=r.dy;
		return *this;
	};
	
   int    x,y,z;
   int   dx, dy;
};





#define SETAEERECT(prc,l,t,w,h)   (prc)->x=(int)(l),(prc)->y=(int)(t),(prc)->dx=(int)(w),(prc)->dy=(int)(h)
#define ISSAMERECT(SRC,TAR) \
	(((TAR)->x==(SRC)->x)&& \
	((TAR)->y==(SRC)->y)&& \
	((TAR)->z==(SRC)->z)&& \
	((TAR)->dx==(SRC)->dx)&& \
	((TAR)->dy==(SRC)->dy))
#define CLONE_RECT(SRC,TAR) \
	(TAR)->x=(SRC)->x; \
	(TAR)->y=(SRC)->y; \
	(TAR)->z=(SRC)->z; \
	(TAR)->dx=(SRC)->dx; \
	(TAR)->dy=(SRC)->dy;
#define RCRIGHT(prc)          (((prc)->x) + ((prc)->dx) - 1)
#define RCBOTTOM(prc)         (((prc)->y) + ((prc)->dy) - 1)
#define ISRECTEMPTY(prc)   (((prc)->dx <= 0) || ((prc)->dy <= 0))
#define RCCOORD(prc,l,t,r,b)  (l)=(prc)->x,(t)=(prc)->y,(r)=RCRIGHT(prc),(b)=RCBOTTOM(prc)
#define GETCORNERS(prc,l,t,r,b)  (l)=(prc)->x,(t)=(prc)->y,(r)=(l)+(prc)->dx,(b)=(t)+(prc)->dy
#define WRECT_TO_CRECT(SRC,DEST) \
	(DEST)->left=(SRC)->x; \
	(DEST)->top=(SRC)->y; \
	(DEST)->bottom=(SRC)->y+(SRC)->dy; \
	(DEST)->right=(SRC)->x+(SRC)->dx;

#define CRECT_TO_WRECT(SRC,DEST) \
	DEST.y=SRC.top;\
	DEST.x=SRC.left;\
	DEST.dx=SRC.Width();\
	DEST.dy=SRC.Height();

#define CENTER(_PT,_RECT) \
	(_PT).x = (_RECT).x+(_RECT).dx/2; \
	(_PT).y = (_RECT).y+(_RECT).dy/2;

#define TOP_CENTER(_PT,_RECT) \
	(_PT).x = (_RECT).x+(_RECT).dx/2; \
	(_PT).y = (_RECT).y;

#define BOTTOM_CENTER(_PT,_RECT) \
	(_PT).x = (_RECT).x+(_RECT).dx/2; \
	(_PT).y = (_RECT).y+(_RECT).dy;

#define LEFT_CENTER(_PT,_RECT) \
	(_PT).x = (_RECT).x; \
	(_PT).y = (_RECT).y+(_RECT).dy/2;

#define RIGHT_CENTER(_PT,_RECT) \
	(_PT).x = (_RECT).x+(_RECT).dx; \
	(_PT).y = (_RECT).y+(_RECT).dy/2;



bool DLL_EXP IntersectRect(WRect *prcDest, const WRect *prcSrc1, const WRect *prcSrc2);
void DLL_EXP UnionRect(WRect *prcResult, const WRect *prcSrc1, const WRect *prcSrc2);

void  win_trace(const char *format, ...);

void* DLL_EXP EG_MALLOC(unsigned int len);
void DLL_EXP EG_FREE(void* p);
class DLL_EXP CObjItem
{
public:
	CObjItem()
	{
	}
	CObjItem(void* pData)
	{
		m_pPrevObj=NULL;
		m_pNextObj=NULL;
		m_pData=pData;

	}
	void* m_pData;
	CObjItem* m_pNextObj;
	CObjItem* m_pPrevObj;
};

class DLL_EXP CObjList{
public:

	CObjList()
	{
		m_pHead=NULL;
		m_pTail=NULL;
		m_nCount=0;
	};
	virtual ~CObjList()
	{
		clear();

	}
	CObjItem* m_pHead;
	CObjItem* m_pTail;
	int m_nCount;

	CObjItem* Next(CObjItem* pItem)
	{
		if(pItem==NULL)
		{
			return this->m_pHead;
		}
		return pItem->m_pNextObj;
	}

	int GetIndex(void* pData)
	{
		int idx=0;
		CObjItem* pItem = this->m_pHead;
		while(pItem!=NULL)
		{
			
			if(pItem->m_pData == pData)
			{
					return idx;
			}
			idx++;
			pItem=pItem->m_pNextObj;
		}

	
	}

	
	
	void add(void* pData)
	{
		CObjItem* pItem=new CObjItem(pData);


		if(this->m_pTail==0)
		{
			m_pTail=m_pHead=pItem;
			m_pTail->m_pNextObj=NULL;
			m_pTail->m_pPrevObj=NULL;
		}
		else
		{
			this->m_pTail->m_pNextObj=pItem;
			pItem->m_pPrevObj=this->m_pTail;
			this->m_pTail=pItem;
		}
		m_nCount++;
	}
	void remove(void* pData)
	{
		CObjItem* pItem = this->m_pHead;
		while(pItem!=NULL)
		{
			if(pItem->m_pData == pData)
			{
					CObjItem* pDelete = pItem;
					if(pItem->m_pPrevObj!=NULL)
					{
						pItem->m_pPrevObj->m_pNextObj=pItem->m_pNextObj;
					}
					else
					{
						this->m_pHead=pItem->m_pNextObj;
					}

					if(pItem->m_pNextObj!=NULL)
					{
						pItem->m_pNextObj->m_pPrevObj=pItem->m_pPrevObj;
					}
					else
					{
						this->m_pTail=pItem->m_pPrevObj;
					}		
					this->m_nCount--;
					pItem=pItem->m_pNextObj;
					delete pDelete;
					continue;
			}
			pItem=pItem->m_pNextObj;
		}

		if(this->m_nCount==0)
		{
			m_pTail=NULL;
			m_pHead=NULL;

		}
	}
	void clear()
	{
		CObjItem* pItem = (CObjItem*)(this->m_pHead);		
		while(pItem!=0)
		{
			CObjItem* pDelete = pItem;
			pItem=pItem->m_pNextObj;
			delete pDelete;

		}
		m_pHead=NULL;
		m_pTail=NULL;
		m_nCount=0;
	}

};

class DLL_EXP CCommonObject {
public:



	CCommonObject* m_pGarbageHead;
	CCommonObject* m_pGarbageTail;
	int	m_nGarbageCnt;
	CCommonObject* m_pNextObj;
	CCommonObject* m_pPrevObj;
	CCommonObject()
	{
		m_pNextObj=NULL;
		m_pPrevObj=NULL;
		m_nGarbageCnt=0;
		m_pGarbageHead=NULL;
		m_pGarbageTail=NULL;
	};
	virtual ~CCommonObject()
	{
		ClearGarbage();
	}

	void AddGarbage(CCommonObject* pG)
	{

		if(this->m_pGarbageTail==0)
		{
			m_pGarbageTail=m_pGarbageHead=pG;
			m_pGarbageTail->m_pNextObj=NULL;
			m_pGarbageTail->m_pPrevObj=NULL;
		}
		else
		{
			this->m_pGarbageTail->m_pNextObj=pG;
			pG->m_pPrevObj=this->m_pGarbageTail;
			this->m_pGarbageTail=pG;
		}
		m_nGarbageCnt++;

	}
	void RemoveGarbage(CCommonObject* pG)
	{
		
		CCommonObject* pItem = this->m_pGarbageHead;
		while(pItem!=NULL)
		{
			if(pItem == pG)
			{
					CCommonObject* pDelete = pItem;
					if(pItem->m_pPrevObj!=NULL)
					{
						pItem->m_pPrevObj->m_pNextObj=pItem->m_pNextObj;
					}
					else
					{
						this->m_pGarbageHead=pItem->m_pNextObj;
					}

					if(pItem->m_pNextObj!=NULL)
					{
						pItem->m_pNextObj->m_pPrevObj=pItem->m_pPrevObj;
					}
					else
					{
						this->m_pGarbageTail=pItem->m_pPrevObj;
					}		
					this->m_nGarbageCnt--;
					pItem=pItem->m_pNextObj;
					delete pDelete;
					continue;
			}
			pItem=pItem->m_pNextObj;
		}

		if(this->m_nGarbageCnt==0)
		{
			m_pGarbageTail=NULL;
			m_pGarbageHead=NULL;

		}
	}
	void ClearGarbage()
	{
		CCommonObject* pItem = (CCommonObject*)(this->m_pGarbageHead);		
		while(pItem!=0)
		{
			CCommonObject* pDelete = pItem;
			pItem=pItem->m_pNextObj;
			delete pDelete;

		}
	}
	
};

#endif


DLL_EXP uint16
ConvertUCS2toUTF8String( const uint8 * source_ptr,
                              uint16  source_len,
                              uint8 * target_ptr,
                              uint16  target_buf_len);
DLL_EXP uint16
ConvertUTF8toUCS2String(const uint8 * source_ptr,
                             uint16  source_len, 
                             uint8 * target_ptr, 
                             uint16  target_buf_len);

DLL_EXP uint16 *
util_wstrncpy ( uint16 * dest, const uint16 * source, uint32 num );

DLL_EXP uint32
util_wstrlen ( const uint16 * s );

DLL_EXP inline int str2wstr(uint8* str,int slen,uint16* wstr,int wslen);

